import re
from random import randint
from newapp.models import User
from django.http import *
from django.shortcuts import *
from django.views import View
from libs.captcha.captcha import captcha  # 导入图片验证码库
from django_redis import get_redis_connection  # 导入redis包
from libs.yuntongxun.sms import CCP
from utils.response_code import RETCODE
from django.contrib.auth import *
from home.models import ArticleCategory,Article
from django.contrib.auth.mixins import LoginRequiredMixin



class RegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        sms_code = request.POST.get('sms_code')
        # 2-2、手机号格式是否正确
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('手机号码格式不正确')
        # 2-3、密码是否符合格式
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password) or not re.match(r'^[0-9a-zA-Z]{8,20}$', password2):
            return HttpResponseBadRequest('密码长度、格式不正确。长度8-20，必须是数字、字母')
        # 2-4、密码和确认密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')
        # 4、保存短信验证码内容到redis中,保存时间1分钟
        redis_conn = get_redis_connection()
        redis_sms_code = redis_conn.get('sms:%s' % mobile)
        if redis_sms_code.decode() != sms_code:
            return HttpResponseBadRequest('短信验证码错误')
        user = User.objects.create_user(username=mobile, mobile=mobile, password=password)


        return HttpResponseRedirect('/')

        # user.set_password(user.password)
        # user.save()
        login(request, user)
        resp = redirect(reverse('home:index'))
        resp.set_cookie('is_login', True)
        resp.set_cookie('login_name', user.username)
        return resp


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        remember = request.POST.get('remember')
        if not all([mobile, password]):
            return render(request, 'login.html', {'msg': '参数不齐全'})
        if not re.match('^1[3-9]\d{9}$', mobile):
            return render(request, 'login.html', {'msg': '手机号码格式不正确'})
        if not re.match('^[a-zA-Z0-9]{8,20}$', password):
            return render(request, 'login.html', {'msg': '密码格式不正确'})
        login_user = authenticate(username=mobile, password=password)
        print(login_user)
        login(request, login_user)
        # resp = redirect(reverse('home:index'))
        next_page= request.Get.get('next')
        if next_page:
            resp = redirect(next_page)
        else:
            resp =redirect(reverse('home:index'))

        if remember != 'on':
            request.session.set_expiry(0)
            resp.set_cookie('is_login', True)
            resp.set_cookie('login_name', login_user.username)
        else:
            request.session.set_expiry(None)
            resp.set_cookie('is_login', True, max_age=14*24*3600)
            resp.set_cookie('login_name', login_user.username, max_age=14*24*3600)
        return resp


class LogoutView(View):

    def get(self,request):
        # 清理session
        logout(request)
        # 退出登录，重定向到登录页
        response = redirect(reverse('home:index'))
        # 退出登录时清除cookie中的登录状态
        response.delete_cookie('is_login')

        return response



class ImageView(View):
    def get(self, request):
        uuid = request.GET.get('uuid')
        if uuid is None:
            return HttpResponse('uuid不存在')
        text, image = captcha.generate_captcha()
        redis_conn = get_redis_connection('default')
        redis_conn.setex(name='img:%s' % uuid, time=300, value=text)
        return HttpResponse(image, content_type='image/jpeg')


# 发送短信验证码视图
class SmsCodeView(View):

    def get(self, request):

        '''
        实现思路：
        1、接收参数
        2、参数验证
            2.1 验证参数是否齐全
            2.2 图片验证码的验证
                连接redis，获取redis中图片验证码
                判断图片验证码是否存在
                    如果图片验证码未过期，我们获取到之后就可以删除图片验证码
                    比对图片验证码（忽略用户大小写）
        3、生成短信验证码
        4、保存短信验证码内容到redis中
        5、发送短信
        6、返回响应信息
        :param request:
        :return:
        '''
        # 1、接收参数
        mobile = request.GET.get('mobile')
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('uuid')
        # 2、参数验证
        # 2.1
        # 验证参数是否齐全
        if not all([mobile, image_code, uuid]):
            return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必要的参数'})
        # 2.2
        # 图片验证码的验证
        # 连接redis，获取redis中图片验证码
        # 创建redis连接对象
        redis_conn = get_redis_connection('default')
        # 根据传来的图片uuid，获取redis中的值
        redis_image_code = redis_conn.get('img:%s' % uuid)
        # 判断图片验证码是否存在
        if redis_image_code is None:
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码已过期'})
        # 如果图片验证码未过期，我们获取到之后就可以删除图片验证码
        try:
            # 删除图形验证码，避免恶意测试图形验证码
            redis_conn.delete('img:%s' % uuid)
        except Exception:
            pass
        # 比对图片验证码（全部转为小写） redis中的数据是bytes类型
        if redis_image_code.decode().lower() != image_code.lower():
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码错误'})
        # 3、生成短信验证码：生成6位数验证码
        sms_code = '%06d' % randint(0, 999999)
        # 为了后期测试方便，我们可以把短信验证码记录到日志中
        print(f'短信验证码：{sms_code}')
        # 4、保存短信验证码内容到redis中,保存时间1分钟
        redis_conn.setex('sms:%s' % mobile, 60, sms_code)
        print(redis_conn.get('sms:%s' % mobile))
        # 5、发送短信
        accId = '8a216da87ba59937017c261424dc21cf'
        accToken = '2cd944d03e2944aeb0ed09b1c597b2bd'
        appId = '8a216da87ba59937017c261425d021d5'
        sms = SmsSDK(accId, accToken, appId)
        sms.sendMessage(1, 18700089747, (sms_code, 1))
        # 6、返回响应信息
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '短信发送成功', 'sms_code': sms_code})


class LoginView(View):
    def get(self, request):
        return render(request, "login.html")

    def post(self, req):
        '''
               实现思路：
               1、接收提交参数
               2、验证参数
                2-1、手机号码是否符合规则
                2-2、密码是否符合规则
               3、用户认证登录
               4、状态保持
               5、根据用户选择的是否记住登录状态进行判断
               6、设置cookie信息，为首页显示服务
               7、跳转到首页
               :param request:
               :return:
               '''

        mobile = req.POST.get('mobile')
        password= req.POST.get('password')
        remember = req.POST.get('remember')
        print(mobile,password)

        if not all([mobile,password]):
            return render(req,'login.html',{'msg':'参数不齐全'})
        if not re.match('^1[3-9]\d{9}$',mobile):
            return render(req,"login.html",{'msg':'手机号码格式错误'})
        if not re.match('^[a-z0-9A-z]{8,28}$',password):
            return render(req,'login.html',{'msg':'密码格式不正确'})
        #3、用户认证登录
        #使用Django系统自带的用户认证代码，将会返回一个user对象。如果账号密码正确，那么就返回对象，否则就返回None
        return_user = authenticate(mobile=mobile, password=password)
        # 4、状态保持
        login(req, return_user)
        #5、根据用户选择的是否记住登录状态进行判断
        resp = redirect(reverse('home:index'))

        if remember!='on':#用户未勾选
            req.session.set_expiry(0)#当浏览器关闭后，清空session
            resp.set_cookie('is_login',True)
            resp.set_cookie('login_name',return_user.username)
        else:#用户勾选
            req.session.set_expiry(None)  # 设置session的过期时间为默认值，这个默认值时间是2周
            resp.set_cookie('is_login', True,max_age=14*24*3600)
            resp.set_cookie('login_name', return_user.username,max_age=14*24*3600)
        return resp
class LogoutView(View):
    def get(self,req):
        logout(req)
        resp = redirect(reverse('home:index'))
        resp.delete_cookie('is_login')
        resp.delete_cookie('login_name')
        return resp
class ForgetPasswordView(View):
    def get(self, request):
        return render(request, 'forget_password.html')

    def post(self,request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        sms_code = request.POST.get('sms_code')
        if not all([mobile,password]):
            return render(request, 'forget_password.html', {'msg':'缺少必要的参数'})
        #2-2、手机号是否符合规则
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return render(request, 'forget_password.html', {'msg': '密码格式不正确'})
        #2-4、判断确认密码是否一致
        if password != password2:
            return render(request, 'forget_password.html', {'msg': '两次密码输入不一致'})
        redis_conn = get_redis_connection('default')
        sms_code_redis = redis_conn.get(f'sms:{mobile}')

        if sms_code_redis is None:
            return render(request, 'forget_password.html',{'msg':'短信验证码过期'})

        if sms_code_redis.decode() != sms_code:
            return render(request, 'forget_password.html', {'msg': '短信验证码错误'})
        redis_conn.delete(f'sms :{mobile}')
        #3、很据手机号码进行用户信息的查询
        userinfo = User.objects.filter(mobile=mobile).first()
        print(userinfo)
        userinfo.set_password(password)
        userinfo.save()

        resp=redirect(reverse('newapp:login'))
        return resp

class UserCenterView(LoginRequiredMixin,View):
    def get(self, request):
        userinfo=request.user#获取已经登录的用户信息
        uu ={
            'mobile':userinfo.mobile,
            'username':userinfo.username,
            'avatar':userinfo.avatar.url if userinfo.avatar else None,
            'desc':userinfo.user_desc
        }
        return render(request, 'usercenter.html',context=uu)

    def post(self,request):
        username= request.POST.get('username')
        desc = request.POST.get('desc')
        avatar = request.FILES.get('avatar')
        print(avatar)
        userinfo= request.user#获取到已经登录的用户信息，并且这个用户是被orm跟踪
        userinfo.username=username
        userinfo.user_desc=desc
        userinfo.avatar=avatar
        userinfo.save()
        #更新到数据库
        resp = redirect(reverse('newapp:usercenter'))
        resp.set_cookie('login_name',username)


        return resp

class WriteBlogView(View):
    def get(self, requset):
        contxt = ArticleCategory.objects.all()
        return render(requset, 'writeblog.html',context={'list':contxt})

    def post(self, request):
        '''
        实现思路：
        1、接收数据
        2、验证数据
        3、数据入库
        4、跳转到指定页面
        :param request:
        :return:
        '''
        # 1、接收数据
        avatar = request.FILES.get('avatar')
        title = request.POST.get('title')
        category_id = request.POST.get('category')
        tags = request.POST.get('tags')
        sumary = request.POST.get('sumary')
        content = request.POST.get('content')
        user = request.user
        print(avatar, title, category_id, sumary, content)
        # 2、验证数据
        # 2-1、参数齐全验证
        if not all([avatar, title, category_id, sumary, content]):

            return HttpResponseBadRequest('参数不齐全')

        # 2-2、判断分类id
        try:
            category = ArticleCategory.objects.filter(pk=category_id).first()
        except ArticleCategory.DoesNotExist:
            return HttpResponseBadRequest('没有该分类信息')
        # 3、数据入库
        try:
            Article.objects.create(
                author=user,
                avatar=avatar,
                title = title,
                category=category,
                tags=tags,
                sumary=sumary,
                content=content
            )

        except Exception as e:
            return HttpResponseBadRequest('发布失败，请稍后重试')
        # 4、跳转到指定页面
        return redirect(reverse('home:index'))
